﻿using ImportMoudel;
using MySql.Data.MySqlClient;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Linq;
using System.Reflection;
using System.Text;

namespace LightingServer.Start
{
    public enum CommandType
    {
        PackageImport,
        DownloadResource,
        Login,
        LoadAllLables,
        QueryLevel2,
        QueryLevel3,
        QueryLevel4,
        QueryLevel5,
        Query,
        GetUsers,
        AddUser,
        DeleteUser,
        UpdateUser
    }

    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
    public class RequestMethodAttribute : Attribute
    {
        public CommandType CommandType { get; set; }
    }

    public class RequestAdapter : IRequestHandler
    {
        private static readonly Dictionary<CommandType, MethodInfo> _methods;

        static RequestAdapter()
        {
            _methods = new Dictionary<CommandType, MethodInfo>();

            foreach(MethodInfo methodInfo in typeof(RequestAdapter).GetMethods())
            {
                object[] attributes = methodInfo.GetCustomAttributes(typeof(RequestMethodAttribute), true);
                if(attributes != null 
                    && attributes.Length > 0
                    && attributes[0] is RequestMethodAttribute)
                {
                    RequestMethodAttribute attribute = attributes[0] as RequestMethodAttribute;
                    _methods[attribute.CommandType] = methodInfo;
                }
            }
        }

        public byte[] GetReponse(Protocol protocol)
        {
            try
            {
                CommandType commandType = (CommandType)Enum.Parse(typeof(CommandType), protocol.CommandID.ToString());
                MethodInfo methodInfo = _methods[commandType];
                return (byte[])methodInfo.Invoke(this, new object[] { protocol.RecevieData });
            }
            catch (Exception ex)
            {
                return new byte[0];
            }
        }

        [RequestMethod(CommandType = CommandType.PackageImport)]
        public byte[] PackageImport(byte[] data)
        {
            RequestHandler handler = new RequestHandler();
            bool isSuccessful = handler.Import(data);
            return new byte[] { isSuccessful ? (byte)1 : (byte)0 };
        }

        [RequestMethod(CommandType = CommandType.DownloadResource)]
        public byte[] DownloadResource(byte[] data)
        {
            RequestHandler handler = new RequestHandler();
            return handler.DownloadResource();
        }

        [RequestMethod(CommandType = CommandType.Login)]
        public byte[] Login(byte[] data)
        {
            RequestHandler handler = new RequestHandler();
            return handler.Login(data);
        }

        [RequestMethod(CommandType = CommandType.LoadAllLables)]
        public byte[] LoadAllLables(byte[] data)
        {
            RequestHandler handler = new RequestHandler();
            return handler.LoadAllLables();
        }

        [RequestMethod(CommandType = CommandType.QueryLevel2)]
        public byte[] QueryLevel2(byte[] data)
        {
            RequestHandler handler = new RequestHandler();
            return handler.QueryLevel2(data);
        }

        [RequestMethod(CommandType = CommandType.QueryLevel3)]
        public byte[]  QueryLevel3(byte[] data)
        {
            RequestHandler handler = new RequestHandler();
            return handler.QueryLevel3(data);
        }

        [RequestMethod(CommandType = CommandType.QueryLevel4)]
        public byte[] QueryLevel4(byte[] data)
        {
            string id = Encoding.UTF8.GetString(data);
            RequestHandler handler = new RequestHandler();
            return handler.QueryLevel4(id);
        }

        [RequestMethod(CommandType = CommandType.QueryLevel5)]
        public byte[] QueryLevel5(byte[] data)
        {
            string id = Encoding.UTF8.GetString(data);
            RequestHandler handler = new RequestHandler();
            return handler.QueryLevel5(id);
        }

        [RequestMethod(CommandType = CommandType.Query)]
        public byte[] Query(byte[] data)
        {
            RequestHandler handler = new RequestHandler();
            return handler.Query(data);
        }

        [RequestMethod(CommandType = CommandType.GetUsers)]
        public byte[] GetUsers(byte[] data)
        {
            RequestHandler handler = new RequestHandler();
            return handler.GetUsers();
        }

        [RequestMethod(CommandType = CommandType.AddUser)]
        public byte[] AddUser(byte[] data)
        {
            RequestHandler handler = new RequestHandler();
            bool isSuceessful = handler.AddUser(data);
            return new byte[] { isSuceessful ? (byte)1 : (byte)0 };
        }

        [RequestMethod(CommandType = CommandType.DeleteUser)]
        public byte[] DeleteUser(byte[] data)
        {
            RequestHandler handler = new RequestHandler();
            string id = Encoding.UTF8.GetString(data);
            bool isSuceessful = handler.DeleteUser(id);
            return new byte[] { isSuceessful ? (byte)1 : (byte)0 };
        }

        [RequestMethod(CommandType = CommandType.UpdateUser)]
        public byte[] UpdateUser(byte[] data)
        {
            RequestHandler handler = new RequestHandler();
            bool isSuceessful = handler.UpdateUser(data);
            return new byte[] { isSuceessful ? (byte)1 : (byte)0 };
        }
    }

    public class RequestHandler
    {
        public bool Commit(byte[] bytes)
        {
            if (bytes == null || bytes.Length == 0)
            {
                return false;
            }

            LightingServerContext.WriteLine("Commit");
            return Import(bytes);
        }

        public bool Import(byte[] bytes)
        {
            try
            {
                ImportHandler handler = new ImportHandler();
                handler.Import(bytes);
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        /// <summary>
        /// 获取静态字典
        /// </summary>
        /// <returns></returns>
        public byte[] DownloadResource()
        {
            try
            {
                return ResourceProvider.Res.ToByteArray();
            }
            catch (Exception ex)
            {
                return new byte[0];
            }
        }

        public byte[] Login(byte[] bytes)
        {
            User sourceUser = User.ParseFrom(bytes);
            User.Builder builder = new User.Builder();
            try
            {
                using (DbConnection conn = LightingServerContext.CreateConnection())
                {
                    using (DbCommand command = conn.CreateCommand())
                    {

                        conn.Open();
                        command.CommandText = "SELECT id, name, password, roleType FROM user WHERE name=@name AND password=@password;";

                        command.Parameters.AddRange(new MySqlParameter[]
                        {
                            new MySqlParameter()
                            {
                                ParameterName = "@name",
                                DbType = DbType.String,
                                Value = sourceUser.Name
                            },
                            new MySqlParameter()
                            {
                                ParameterName = "@password",
                                DbType = DbType.String,
                                Value = sourceUser.Password
                            },
                        });

                        using (var reader = command.ExecuteReader())
                        {
                            while (reader.Read())
                            {
                                builder.SetId(reader["id"].ToString());
                                builder.SetName(reader["name"].ToString());
                                builder.SetPassword(reader["password"].ToString());
                                builder.SetRoleType(uint.Parse(reader["roleType"].ToString()));
                                break;
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
            }
            return builder.Build().ToByteArray();
        }

        public byte[] LoadAllLables()
        {
            Res.Builder builder = new Res.Builder();
            try
            {
                LightingServerContext.WriteLine("LoadAllLables");
                using (DbConnection conn = LightingServerContext.CreateConnection())
                {
                    using (DbCommand command = conn.CreateCommand())
                    {
                        conn.Open();
                        command.CommandText = "SELECT DISTINCT lable FROM lighting ORDER BY lable;";

                        using (var reader = command.ExecuteReader())
                        {
                            while (reader.Read())
                            {
                                string lable = reader["lable"] != null ? reader["lable"].ToString().Trim() : null;
                                if (!string.IsNullOrEmpty(lable))
                                {
                                    ResItem.Builder itemBuilder = new ResItem.Builder();
                                    itemBuilder.SetItemName(lable);
                                    builder.Res_List.Add(itemBuilder.Build());
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
            }
            return builder.Build().ToByteArray();
        }

        public byte[] QueryLevel2(byte[] bytes)
        {
            LightingQueryService service = new LightingQueryService();
            Lightings lightings = service.QueryLevel2(QueryParameter2.ParseFrom(bytes));
            return lightings.ToByteArray();
        }

        public byte[] QueryLevel3(byte[] bytes)
        {
            LightingQueryService service = new LightingQueryService();
            Lightings lightings = service.QueryLevel3(QueryParameter3.ParseFrom(bytes));
            return lightings.ToByteArray();
        }

        public byte[] QueryLevel4(string id)
        {
            LightingQueryService service = new LightingQueryService();
            Lighting lighting = service.QueryLevel4(id);
            return lighting.ToByteArray();
        }

        public byte[] QueryLevel5(string id)
        {
            LightingQueryService service = new LightingQueryService();
            Lighting lighting = service.QueryLevel5(id);
            return lighting.ToByteArray();
        }

        public byte[] Query(byte[] bytes)
        {
            LightingQueryService service = new LightingQueryService();
            Lightings lightings = service.Query(LightingQuery.ParseFrom(bytes));
            return lightings.ToByteArray();
        }

        public byte[] GetUsers()
        {
            LightingQueryService service = new LightingQueryService();
            Users users = service.GetUsers();
            return users.ToByteArray();
        }

        public bool AddUser(byte[] bytes)
        {
            LightingQueryService service = new LightingQueryService();
            return service.AddUser(User.ParseFrom(bytes));
        }

        public bool DeleteUser(string id)
        {
            LightingQueryService service = new LightingQueryService();
            return service.DeleteUser(id);
        }

        public bool UpdateUser(byte[] bytes)
        {
            LightingQueryService service = new LightingQueryService();
            return service.UpdateUser(User.ParseFrom(bytes));
        }
    }
}
